﻿//------------------------------------------------------------------------------------------------------
// <summary>
//     The following code is allowed to be used inernally in Pfizer China only, 
//     you are not permitted neither to use the contents nor disclose it in any
//     manner to third parties.
// </summary>
// <copyright file="DataContextManager.cs" company="Pfizer China">
//     Copyright (c) Pfizer China. All rights reserved.
// </copyright>
//------------------------------------------------------------------------------------------------------

//the predefine code below is just for the unit test, when unit test please enable the code below
//#define MockUp
using System;
using System.Data;
using System.Data.Common;
using System.Data.Linq;
using System.Data.SqlClient;
using System.Linq;
using System.Linq.Expressions;
using System.Web;
using SystemFrameWork;
using Entity.Model;




namespace DAL
{
    public class DataContextManager
    {
        private const string DataContext = "DataContext";

        /// <summary>
        /// sql connetion string
        /// </summary>
        private static string conStr = ConfigurationHelper.SqlConnectionString;

        /// <summary>
        /// place the data context to this static variable for unit test
        /// </summary>
        /// Added by Li Xing
        private static BeOnDutyModelDataContext beOnDutyModelDataContext;

        public BeOnDutyModelDataContext CurrentDataContext
        {
            get
            {
#if MockUp
                if (passDataContext == null)
                {
                    passDataContext = CreateDataContext();
                }

                return passDataContext;
#endif
                if (this.Context == null)
                {
                    this.Context = this.CreateDataContext();
                }

                return this.Context;
            }
        }

        internal DbTransaction Transaction
        {
            get
            {
                return this.CurrentDataContext.Transaction;
            }

            set
            {
                this.CurrentDataContext.Transaction = value;
            }
        }

        private BeOnDutyModelDataContext Context
        {
            get
            {
                if (HttpContext.Current.Items[DataContext] != null)
                {
                    return HttpContext.Current.Items[DataContext] as BeOnDutyModelDataContext;
                }
                else
                {
                    return null;
                }
            }

            set
            {
                HttpContext.Current.Items[DataContext] = value;
            }
        }

        /// <summary>
        /// firstly rollback the transaction.
        /// </summary>
        public void CloseDataContext()
        {
            try
            {
                if (this.Context != null)
                {
                    this.RollBackTransaction();
                    this.Context.Dispose();
                    this.Context = null;
                }
            }
            catch (Exception ex)
            {
                //LogHelper.Log(LogLevel.Error, ex);
            }
        }

        public void Refresh(object entity)
        {
            this.CurrentDataContext.Refresh(RefreshMode.KeepCurrentValues, entity);
        }

        public void Commit()
        {
            try
            {
                this.CurrentDataContext.SubmitChanges();
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public void SetLoadOptions<T>(Expression<Func<T, object>>[] expressions)
        {
            DataLoadOptions op = this.GetLoadOptions();

            for (int i = 0; i < expressions.Count(); i++)
            {
                op.LoadWith(expressions[i]);
            }

            this.CurrentDataContext.LoadOptions = op;
        }

        public void SetLoadOptions(DataLoadOptions option)
        {
            this.CurrentDataContext.LoadOptions = option;
        }

        public DbConnection GetConnection()
        {
            return this.CurrentDataContext.Connection;
        }

        public SqlTransaction BeginTransaction()
        {
            try
            {
                if (this.CurrentDataContext.Connection.State == ConnectionState.Closed)
                {
                    this.CurrentDataContext.Connection.Open();
                }

                DbTransaction trans = this.CurrentDataContext.Connection.BeginTransaction();

                this.Transaction = trans;

                ///SqlHelper.Transaction = trans as SqlTransaction;
                ///these code is for DataContextManager and SqlHelper has the same Transaction.
                return trans as SqlTransaction;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }
        }

        public void CommitTransaction()
        {
            /// LogHelper.Log(LogLevel.Fatal, "Not Commit this transaction in DataContext");
            if (this.Transaction != null)
            {
                try
                {
                    this.Transaction.Commit();
                    this.Transaction = null;
                    ///SqlHelper.Transaction = null;

                    ///LogHelper.Log(LogLevel.Fatal, "Commit this transaction in DataContext");
                }
                catch (Exception ex)
                {
                    //LogHelper.Log(LogLevel.Error, ex);
                }
            }
        }

        public void RollBackTransaction()
        {
            /// LogHelper.Log(LogLevel.Fatal, "Not RollBack This Transaction in DataContext");
            if (this.Transaction != null)
            {
                try
                {
                    this.Transaction.Rollback();

                    ///LogHelper.Log(LogLevel.Fatal, "RollBack this transaction in DataContext");
                    this.Transaction = null;
                    ///SqlHelper.Transaction = null;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        private DataLoadOptions GetLoadOptions()
        {
            DataLoadOptions options = new DataLoadOptions();

            return options;
        }

        private BeOnDutyModelDataContext CreateDataContext()
        {
            BeOnDutyModelDataContext dataContext = new BeOnDutyModelDataContext(conStr);
            int timeOutSetting = ConfigurationHelper.ConnetionTimeOut;
            dataContext.CommandTimeout = timeOutSetting;

            dataContext.LoadOptions = this.GetTheLoadOptions();
            return dataContext;
        }

        /// <summary>
        /// set the data load options
        /// </summary>
        /// <returns></returns>
        private DataLoadOptions GetTheLoadOptions()
        {
            DataLoadOptions options = new DataLoadOptions();

            //---Candidate relative---//
            //options.AssociateWith<Candidate>(c => c.CandidateAccounts.Where(rf => rf.RecordStatus == (byte)RecordStatus.RecordActive));

            return options;
        }
    }
}
